 /*
 * UMLSynch - VPSDE plugin part
 * http://umlsynch.googlecode.com
 *
 * Copyright 2008-2010, Evgeny Alexeyev
 * Licensed under the EPL - v1.0
 * http://www.eclipse.org/legal/epl-v10.html
 *
 */

package com.googlecode.umlsynch.vpsde.plugins.menuitem.dependency;
import java.awt.event.ActionEvent;
import java.util.Iterator;

import com.googlecode.umlsynch.rpc.IEditorRpc;
import com.googlecode.umlsynch.rpc.IIndexerRpc;
import com.googlecode.umlsynch.rpc.TClassDescriptor;
import com.googlecode.umlsynch.rpc.IIndexerRpc.TRelationRpc;
import com.googlecode.umlsynch.rpc.base.IDebug;
import com.googlecode.umlsynch.vpsde.rpc.ClientFactory;
import com.googlecode.umlsynch.vpsde.rpc.TVPDebug;
import com.googlecode.umlsynch.vpsde.rpc.VPSDEDiagramManager.VPClassDiagramManager;
import com.googlecode.umlsynch.vpsde.rpc.VPSDEDiagramManager.VPObjectDiagramManager;
import com.googlecode.umlsynch.vpsde.rpc_old.EclipseOperationServer.IEclipseOperationServer;
import com.googlecode.umlsynch.vpsde.rpc_old.EclipseOperationServer.TEclipseOperationServerCaller;
import com.googlecode.umlsynch.vpsde.rpc_old.EclipseOperationServer.VPSDEClassDescription;
import com.vp.plugin.ApplicationManager;
import com.vp.plugin.action.VPAction;
import com.vp.plugin.action.VPContext;
import com.vp.plugin.action.VPContextActionController;
import com.vp.plugin.diagram.IDiagramElement;
import com.vp.plugin.diagram.IDiagramUIModel;
import com.vp.plugin.diagram.shape.IClassUIModel;
import com.vp.plugin.model.IAssociation;
import com.vp.plugin.model.IClass;
import com.vp.plugin.model.IConnector;
import com.vp.plugin.model.IModelElement;

public class ActionController implements VPContextActionController {

	private IEclipseOperationServer eclop = TEclipseOperationServerCaller.instance();

	private VPClassDiagramManager VPClassDM = VPClassDiagramManager.instance();
	private VPObjectDiagramManager ObjDM = new VPObjectDiagramManager();

	private IDebug debug = new TVPDebug();

	public void performAction(VPAction action, VPContext context, ActionEvent event) {
		
		debug.Debug(action.getActionId());

		// Selected elements on diagram
		IDiagramElement[] selectedElements = context.getDiagram().getSelectedDiagramElement();

		// Action provider Class, Package etc
		IDiagramElement selectedElement = context.getDiagramElement();
		
		
		// Model element, which provided action   
		IModelElement modelElement = context.getModelElement();
		
		TClassDescriptor inClass = new TClassDescriptor();
		inClass.name = new String(selectedElement.getMetaModelElement().getName());
		inClass.file.path = VPClassDM.
		  GetClasPropery(selectedElement.getModelElement(), VPClassDiagramManager.PROP_CLASS_FILE_NAME);
		
		inClass.file.project = VPClassDM.
		  GetClasPropery(selectedElement.getModelElement(), VPClassDiagramManager.PROP_CLASS_PROJECT_NAME);

		if (inClass.file.project == null)
			inClass.file.project = ApplicationManager.instance().getProjectManager().getProject().getName();


		debug.Debug("Model Element:" + 	modelElement.getName());
		
		// Cut action prefix:
		String substr = "com.googlecode.umlsynch.vpsde.plugins.menuitem.dependency.ClassRefactoring.";
		String actionId = action.getActionId();
		
		actionId = action.getActionId().substring(substr.length(), actionId.length());
		
		if (actionId.equalsIgnoreCase("Generalization") 
				  || actionId.equalsIgnoreCase("Nested")
				  || actionId.equalsIgnoreCase("Dependency")
				  || actionId.equalsIgnoreCase("Base")
				  || actionId.equalsIgnoreCase("Composition")
				  || actionId.equalsIgnoreCase("Association")
				  || actionId.equalsIgnoreCase("Aggregation")) {

			IIndexerRpc indexer = ClientFactory.getInstance().getIndexer();

			TClassDescriptor[] retall = 
				indexer.GetClassRelations(inClass, GetRelationType(actionId), null);
			
			if (retall != null) {
				this.AddClassRelations(context, selectedElement, retall, actionId);
			}
		} 
		else if (actionId.equalsIgnoreCase("DumpAllComponents")) {			
			DumpAllComponents(context);
		} 
		else if (actionId.equalsIgnoreCase("OpenClass")) {	
			IEditorRpc editor = ClientFactory.getInstance().getEditor();
			editor.OpenClass(inClass);
		} 
		else if (actionId.equalsIgnoreCase("OpenImplementation")) {
			IEditorRpc editor = ClientFactory.getInstance().getEditor();
			// Open the constructor of class if class model element selected 
			editor.OpenMethodImplementation(inClass.operations[0]);
			debug.Debug("Open Implementation EXIT");
		} 
		else if (actionId.equalsIgnoreCase("UpdateClass")) {
			IIndexerRpc indexer = ClientFactory.getInstance().getIndexer();
			TClassDescriptor result  = indexer.GetClassInfo(inClass);
			
			if (result != null) {
				debug.Note("Get Class Data:" + result.name + result.file.path);

				if (result.operations != null) {					
					debug.Debug("M1");
					VPClassDM.AddClassOperations(context, (IClass)selectedElement.getModelElement(), result);
				}
				if (result.members != null)
				{
					debug.Debug("M2");
					VPClassDM.AddClassMembers(context, selectedElement, result);
				}
				debug.Debug("M3");
				if (inClass.file.path == null) {
					VPClassDM.SetClasPropery(selectedElement.getModelElement(),
							VPClassDiagramManager.PROP_CLASS_FILE_NAME, result.file.path);
				}
			}
			debug.Debug("Update Class complete");
		} else if (actionId.equalsIgnoreCase("MakeObjectsDiagram")) {
			boolean isAnyClassSelected = false;
			for (int i=0; i<selectedElements.length; ++i) {
				if (selectedElements[i] instanceof IClassUIModel) {
					debug.Debug("Find out that class is selected");
					isAnyClassSelected = true;
					break;
				}
			}
			if (isAnyClassSelected) {
				debug.Debug("Create Diagram");
				IDiagramUIModel diag = ObjDM.CreateSequenceDiagram(modelElement.getName() + "SequenceDiagram");

				for (int i=0; i<selectedElements.length; ++i) {
					if (selectedElements[i] instanceof IClassUIModel) {
						IDiagramElement lldiag = 
							ObjDM.AddLifeLineToDiagram(diag, 
									selectedElements[i].getModelElement().getName(),
									selectedElements[i].getModelElement());
						
						// Copy the Class file Name property
						String prop = VPClassDM.GetClasPropery(selectedElements[i].getModelElement(), VPClassDM.PROP_CLASS_FILE_NAME);
						ObjDM.SetObjectPropery(lldiag.getModelElement(), ObjDM.PROP_CLASS_FILE_NAME, prop);
					} 
				}
				
				selectedElement.getModelElement().addSubDiagram(diag);
			}
		}
	}

	  public TRelationRpc GetRelationType(String str)
	  {
			if (str.equalsIgnoreCase("Generalization")) {
				return TRelationRpc.CLASS_GENERALIZATION;
			} 
			if (str.equalsIgnoreCase("Base")) {
				return TRelationRpc.CLASS_BASE;
			} 
			if (str.equalsIgnoreCase("Aggregation")) {
				return TRelationRpc.CLASS_AGGREGATION;
			} 
			if (str.equalsIgnoreCase("Realization")) {
				return TRelationRpc.CLASS_REALIZATION;
			} 
			if (str.equalsIgnoreCase("Nested")) {
				return TRelationRpc.CLASS_NESTED;
			} 
			if (str.equalsIgnoreCase("Dependency")) {
				return TRelationRpc.CLASS_DEPENDENCY;
			} 
			if (str.equalsIgnoreCase("Association")) {
				return TRelationRpc.CLASS_ASSOCIATION;
			} 
			if (str.equalsIgnoreCase("Composition")) {
				return TRelationRpc.CLASS_COMPOSITION;
			}
			return null; 
	  }
	
	private void DumpAllComponents(VPContext context) {
		Iterator iter = context.getDiagram().diagramElementIterator();

        /* 
         * Print all components on diagram
         */
		while (iter.hasNext())
		{
			IDiagramElement diagElement = (IDiagramElement)iter.next();

			debug.Debug("Model Element Class: " + diagElement.getClass().getName() + 
					" Shape Type:" + diagElement.getShapeType());

			IModelElement mElement = diagElement.getModelElement();
			if (mElement != null) {
				debug.Debug("  Name:" +
						mElement.getName() + " Model ClassName:" + 
						mElement.getClass().getName());
			}

			if (mElement instanceof IAssociation) {
				IAssociation mAss = (IAssociation)mElement;
				debug.Debug("ASSOCIATION: " + mAss.getDirection() + " ModelType " +
						mAss.getModelType() );


			}
		}

        /* 
         * Print all connectes for the selected element
         */
		IDiagramElement selectedElement = context.getDiagramElement();
		Iterator iter2 = selectedElement.fromConnectorIterator();
		while ((iter2 != null) && iter2.hasNext())
		{
			IConnector connectorElement = (IConnector)iter2.next();
			if (connectorElement != null ) {
				debug.Debug("Model Connector Element Class: " + connectorElement.getClass().getName());
			} else {
				debug.Debug("Model Connector Element Class: IS NULL"); 
			}
		}			
		debug.Debug("COMPLETED SHOW ALL");
	}

	private void AddClassRelations(VPContext context, IDiagramElement de, 
			TClassDescriptor[] superclasses, String relationType) {

		// 0 - element an updated class
		for (int i=1; (superclasses != null) && (i< superclasses.length); i++)
		{
			IDiagramElement newElement = 
				VPClassDM.AddConnectedClass(context.getDiagram(), de, superclasses[i].name, relationType);

			VPClassDM.SetClasPropery(newElement.getModelElement(), 
					VPClassDM.PROP_CLASS_FILE_NAME, superclasses[i].name);
		}

		// Save filename property
		String prop = 
			VPClassDM.GetClasPropery(de.getModelElement(), VPClassDM.PROP_CLASS_FILE_NAME);

		if ((prop == null) || prop.isEmpty()) {
			VPClassDM.SetClasPropery(de.getModelElement(), 
					VPClassDM.PROP_CLASS_FILE_NAME, superclasses[0].file.path);
		}
	}
	
	public void update(VPAction action, VPContext context) {
	}

}
